document.addEventListener('DOMContentLoaded', () => {
    const orb = document.getElementById('orb');
    const percentageDisplay = document.getElementById('percentage-display');
    const toggleButton = document.getElementById('toggle-button');
    const statusDisplay = document.getElementById('status-display');

    let isActive = false;
    let animationFrameId;

    // Orb animation state
    let orbX = 0, orbY = 0;
    let targetX = 0, targetY = 0;
    let orbAngle = 0;
    const maxDriftRadius = 137.5;
    const angleDriftFactor = 0.3;

    let currentPercentage = 100.0;
    let targetPercentage = 100.0;

    // Parameters for RNG analysis
    const numBins = 10;
    const sampleSize = 200; // how many random values per tick

    function getRandomSample() {
        const buffer = new Uint32Array(sampleSize);
        window.crypto.getRandomValues(buffer);
        return Array.from(buffer).map(v => v / (0xFFFFFFFF + 1));
    }

    function chiSquareUniform(samples, bins) {
        const counts = new Array(bins).fill(0);
        samples.forEach(val => {
            const idx = Math.min(bins - 1, Math.floor(val * bins));
            counts[idx]++;
        });

        const expected = samples.length / bins;
        let chi2 = 0;
        counts.forEach(c => {
            const diff = c - expected;
            chi2 += (diff * diff) / expected;
        });

        // degrees of freedom = bins - 1
        const df = bins - 1;
        // approximate p-value using survival function of chi2
        // (simplified upper-tail approximation)
        const k = df / 2;
        const x = chi2 / 2;
        let p = Math.exp(-x) * Math.pow(x, k - 1); // rough
        p = Math.min(1, Math.max(0, p));
        return p;
    }

    function updateLogic() {
        if (!isActive) return;

        // Pull entropy from OS and run χ²
        const sample = getRandomSample();
        const p = chiSquareUniform(sample, numBins);

        // Convert p-value (0–1) to 0–100%, but invert so high = more "aligned"
        targetPercentage = (1 - p) * 100;

        // Separate drift randomizer for orb angle
        const driftValue = Math.random();
        orbAngle += (driftValue - 0.5) * angleDriftFactor;

        setTimeout(updateLogic, 200);
    }

    function animate() {
        const smoothingFactor = 0.05;
        currentPercentage += (targetPercentage - currentPercentage) * smoothingFactor;

        const radius = maxDriftRadius * (1 - currentPercentage / 100);
        targetX = radius * Math.cos(orbAngle);
        targetY = radius * Math.sin(orbAngle);

        orbX += (targetX - orbX) * smoothingFactor;
        orbY += (targetY - orbY) * smoothingFactor;

        percentageDisplay.textContent = `${currentPercentage.toFixed(2)}%`;

        const percentFraction = currentPercentage / 100;
        const gold = { r: 255, g: 215, b: 100 };
        const white = { r: 255, g: 255, b: 255 };
        const r = Math.round(white.r + (gold.r - white.r) * percentFraction);
        const g = Math.round(white.g + (gold.g - white.g) * percentFraction);
        const b = Math.round(white.b + (gold.b - white.b) * percentFraction);
        const currentColor = `rgb(${r}, ${g}, ${b})`;

        orb.style.backgroundColor = currentColor;
        orb.style.boxShadow = `0 0 ${15 + percentFraction * 30}px ${currentColor}, 0 0 ${25 + percentFraction * 50}px ${currentColor}`;
        percentageDisplay.style.color = currentColor;
        orb.style.transform = `translate(${orbX}px, ${orbY}px) scale(${1 + percentFraction * 0.2})`;

        animationFrameId = requestAnimationFrame(animate);
    }

    toggleButton.addEventListener('click', () => {
        isActive = !isActive;
        if (isActive) {
            toggleButton.textContent = 'Stop';
            statusDisplay.textContent = 'Status: Alignment Active';
            updateLogic();
        } else {
            toggleButton.textContent = 'Start';
            statusDisplay.textContent = 'Status: Idle';
            targetPercentage = 100;
        }
    });

    animate();
});
